<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  class valuePair {
    constructor(key, value) {
      this.key = key
      this.value = value
    }
  }

  class Dictionary {
    items = {}
    constructor() {
    }

    toStr (key) {
      if (key === null) {
        return 'NULL'
      } else if (key === undefined) {
        return 'UNDEFINED'
      } else if (typeof key === 'string' && key instanceof String) {
        return key
      } else {
        return JSON.stringify(key)
      }
    }

    set (key, val) {
      if (key != null && val != null) {
        const keyStr = this.toStr(key)
        this.items[keyStr] = new valuePair(key, val)
        return true
      }
      return false
    }

    get (key) {
      if (key != null) {
        return this.items[this.toStr(key)]?.value
      }
    }

    has (key) {
      return this.toStr(key) in this.items
    }

    clear () {
      this.items = {}
    }

    keys () {
      return this.keyValues().map(o => o.key)
    }

    values () {
      return this.keyValues().map(o => o.value)
    }

    keyValues () {
      return Object.values(this.items)
    }

    forEach (cb) {
      const kv = this.keyValues()
      for (let i = 0; i < kv.length; i ++) {
        cb(kv[i].key, kv[i].value, kv)
      }
    }
  }

  const dictionary = new Dictionary()

  dictionary.set('a', 'a')
  dictionary.set({ a: 1 }, { a: 1 })
  dictionary.set(true, true)

  dictionary.forEach((k, v, kv) => {
    console.log(k)
    console.log(v)
    console.log(kv)
  })
</script>
</body>
</html>
